package yzrilyzr.simplesynth.app;
import static yzrilyzr.simplesynth.app.AppInstance.*;
import static yzrilyzr.util.AndroidUtil.ctx;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.media.midi.MidiDevice;
import android.media.midi.MidiDeviceInfo;
import android.media.midi.MidiManager;
import android.media.midi.MidiOutputPort;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.OpenableColumns;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.WindowManager;
import android.widget.*;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.SeekBar.OnSeekBarChangeListener;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import yzrilyzr.activity.CrashActivity;
import yzrilyzr.ui.MyDialog;
import yzrilyzr.ui.ViewHolder;
import yzrilyzr.ui.ViewHolderAdapter;
import yzrilyzr.util.AndroidUtil;
import yzrilyzr.util.FileUtil;
import yzrilyzr.util.Logger;
import yzrilyzr.util.MIDIFile;
import yzrilyzr.util.Util;

public class MainActivity extends Activity{
	Runnable updateRunnable;
	Handler handler=new Handler();
	private MidiManager midiManager;
	@Override
	protected void onCreate(Bundle savedInstanceState){
		super.onCreate(savedInstanceState);
		AndroidUtil.setCtx(getApplication());
		CrashActivity.initUEH(this,"");
		MyDialog.setDefaultType(WindowManager.LayoutParams.TYPE_APPLICATION);
		/*Logger.setEnabled(true);
		 Logger.setPrintException(true);
		 Logger.setPrintToConsole(true);
		 Logger.setExceptionFilter(false);
		 CrashActivity.initFWConsole(this);*/
		if(CrashActivity.checkIfCrash(this)){
			finish();
			return;
		}
		getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
		initPlaylist();
		startService(new Intent(this,PlayerService.class));
		setContentView(R.layout.main);
		osc=findViewById(R.id.mainOscilloscopeView1);
		final ToggleButton but=findViewById(R.id.mainToggleButton1);
		but.setOnCheckedChangeListener(new OnCheckedChangeListener(){
			@Override
			public void onCheckedChanged(CompoundButton p1,boolean p2){
				if(p2) NativePlayer.play();
				else NativePlayer.pause();
			}
		});
		final ToggleButton but2=findViewById(R.id.mainToggleButton2);
		but2.setChecked(sustain);
		but2.setOnCheckedChangeListener(new OnCheckedChangeListener(){
			@Override
			public void onCheckedChanged(CompoundButton p1,boolean p2){
				sustain=p2;
				setChannelArgs();
			}
		});
		final ToggleButton but3=findViewById(R.id.mainToggleButton3);
		but3.setChecked(limit);
		but3.setOnCheckedChangeListener(new OnCheckedChangeListener(){
			@Override
			public void onCheckedChanged(CompoundButton p1,boolean p2){
				limit=p2;
				setChannelArgs();
			}
		});
		Button usesf2t=findViewById(R.id.mainToggleButtonSoundbank);
		usesf2t.setOnClickListener(new OnClickListener(){
			@Override
			public void onClick(View v){
				AlertDialog.Builder builder=new AlertDialog.Builder(MainActivity.this);
				builder.setTitle("选择文件");
				File dir=getExternalFilesDir("Soundbank");
				if(!dir.exists()) dir.mkdirs();
				final File[] f=dir.listFiles();
				if(f==null){
					AndroidUtil.toast("文件不可用");
					return;
				}
				CharSequence[] items=new CharSequence[f.length];
				for(int i=0;i<f.length;i++){
					items[i]=f[i].getName();
				}
				builder.setItems(items,new DialogInterface.OnClickListener(){
					@Override
					public void onClick(DialogInterface dialog,int which){
						try{
							NativePlayer.loadSoundbank(f[which].getAbsolutePath());
							AndroidUtil.toast("音源加载完毕");
						}catch(Exception e){
							AndroidUtil.toast("文件不可用");
							AndroidUtil.toast(Util.getStackTrace(e));
						}
					}
				});
				builder.setNeutralButton(R.string.default_instrument,new DialogInterface.OnClickListener(){
					@Override
					public void onClick(DialogInterface dialog,int which){
						NativePlayer.defaultInstrument();
					}
					});
				builder.setPositiveButton(R.string.import_soundbank,new DialogInterface.OnClickListener(){
					@Override
					public void onClick(DialogInterface dialog,int which){
						Intent intent=new Intent(Intent.ACTION_GET_CONTENT);
						intent.setType("*/*"); // 允许所有文件类型，或者指定具体类型如 "audio/*"
						intent.addCategory(Intent.CATEGORY_OPENABLE);
						try{
							// 使用Intent.createChooser确保总是显示选择器
							startActivityForResult(Intent.createChooser(intent,"选择音源文件"),IMPORT_SOUNDBANK_REQUEST_CODE);
						}catch(ActivityNotFoundException ex){
							AndroidUtil.toast("请安装文件管理器应用");
						}
					}
				});
				builder.setNegativeButton(R.string.cancel,new DialogInterface.OnClickListener(){
					@Override
					public void onClick(DialogInterface dialog,int which){
						dialog.dismiss();
					}
				});
				// 创建并显示对话框
				AlertDialog dialog=builder.create();
				dialog.show();
			}
		});
		final TextView tv=findViewById(R.id.mainTextView1);
		final TextView tv2=findViewById(R.id.mainTextView2);
		final TextView tvload=findViewById(R.id.mainTextViewLoadChannel);
		final ProgressBar prog=findViewById(R.id.mainProgressBar1);
		prog.setMax(1000);
		updateRunnable=new Runnable(){
			@Override
			public void run(){
				tv.setText(String.format("Processing:%d",NativePlayer.getCurrentProcessingNoteCount()));
				tv2.setText(String.format("Post:%d",NativePlayer.getPostedEventCount()));
				prog.setSecondaryProgress(800);
				prog.setProgress((int)(800*NativePlayer.getProcessTime()/NativePlayer.getProcessStandardTime()));
				//adap.notifyDataSetChanged();
				if(updateRunnable!=null) handler.postDelayed(this,100);
			}
		};
		ListView l=findViewById(R.id.mainListView1);
		l.setAdapter(new ViewHolderAdapter(){
			@Override
			public ViewHolder createHolder(Context p1){
				return new ViewHolder(new TextView(MainActivity.this)){
					@Override
					public void set(int p1){
						TextView tv=(TextView)get();
						tv.setTextColor(0xff000000);
						String name1=name.get(p1);
						name1=FileUtil.name(name1);
						int i=name1.lastIndexOf(".");
						if(i!=-1) name1=name1.substring(0,i);
						tv.setText(p1+" "+name1);
					}
				};
			}
			@Override
			public int getCount(){
				return name.size();
			}
		});
		l.setOnItemClickListener(new OnItemClickListener(){
			@Override
			public void onItemClick(AdapterView<?> p1,View p2,int p3,long p4){
				NativePlayer.reset();
				currentPlay=p3;
			}
		});
		l.setOnItemLongClickListener(new OnItemLongClickListener(){
			@Override
			public boolean onItemLongClick(AdapterView<?> p1,View p2,final int p3,long p4){
				new MyDialog.Builder(MainActivity.this).setItems(new String[]{"导出为wav"},new DialogInterface.OnClickListener(){
					@Override
					public void onClick(DialogInterface p1,int p2){
						if(p2==0){
							try{
								byte[] b=Util.read(new FileInputStream(map.get(name.get(currentPlay))));
								NativePlayer.export(b,0,getExternalFilesDir("export")+"/"+name.get(currentPlay)+".wav",48000);
							}catch(FileNotFoundException e){
								AndroidUtil.toast("导出失败");
							}
						}
					}
				}).show();
				return true;
			}
		});
		mainExpr=Util.readwithN(getFilesDir()+"/mainExpr");
		updateRunnable.run();
		// 在 Activity 或 Service 中
		if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
			midiManager=(MidiManager)getSystemService(Context.MIDI_SERVICE);
			// 监听 MIDI 设备连接
			midiManager.registerDeviceCallback(new MidiManager.DeviceCallback(){
				@Override
				public void onDeviceAdded(MidiDeviceInfo device){
					// 当新设备（如 USB 键盘）连接时触发
					openMidiDevice(device);
				}
			},new Handler(Looper.getMainLooper()));
		}
	}
	private static final int IMPORT_SOUNDBANK_REQUEST_CODE=1001;
	@Override
	protected void onActivityResult(int requestCode,int resultCode,Intent data){
		super.onActivityResult(requestCode,resultCode,data);
		if(requestCode==IMPORT_SOUNDBANK_REQUEST_CODE&&resultCode==RESULT_OK){
			if(data!=null&&data.getData()!=null){
				Uri uri=data.getData();
				importSoundbankFile(uri);
			}
		}
	}
	private void importSoundbankFile(Uri uri){
		try{
			// 获取目标目录
			File destDir=getExternalFilesDir("Soundbank");
			if(!destDir.exists()) destDir.mkdirs();
			// 从URI获取文件名
			String fileName=getFileNameFromUri(uri);
			if(fileName==null){
				AndroidUtil.toast("无法获取文件名");
				return;
			}
			// 创建目标文件
			File destFile=new File(destDir,fileName);
			// 复制文件
			try(InputStream is=getContentResolver().openInputStream(uri);OutputStream os=new FileOutputStream(destFile)){
				byte[] buffer=new byte[1024];
				int length;
				while((length=is.read(buffer))>0){
					os.write(buffer,0,length);
				}
				os.flush();
				AndroidUtil.toast("文件导入成功: "+fileName);
				// 可以在这里刷新文件列表或执行其他操作
			}catch(IOException e){
				AndroidUtil.toast("文件复制失败: "+e.getMessage());
			}
		}catch(Exception e){
			AndroidUtil.toast("导入失败: "+e.getMessage());
		}
	}
	private String getFileNameFromUri(Uri uri){
		String fileName=null;
		String scheme=uri.getScheme();
		if(scheme!=null&&scheme.equals("content")){
			Cursor cursor=getContentResolver().query(uri,null,null,null,null);
			if(cursor!=null&&cursor.moveToFirst()){
				int index=cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
				if(index!=-1){
					fileName=cursor.getString(index);
				}
				cursor.close();
			}
		}
		if(fileName==null){
			fileName=uri.getPath();
			int cut=fileName.lastIndexOf('/');
			if(cut!=-1){
				fileName=fileName.substring(cut+1);
			}
		}
		return fileName;
	}
	@Override
	protected void onResume(){
		super.onResume();
		openFile(getIntent());
	}
	@Override
	protected void onNewIntent(Intent intent){
		super.onNewIntent(intent);
		openFile(intent);
	}
	@Override
	protected void onPause(){
		super.onPause();
		Util.write(getFilesDir()+"/mainExpr",mainExpr);
	}
	@Override
	protected void onDestroy(){
		super.onDestroy();
		updateRunnable=null;
		AppInstance.osc=null;
	}
	private void openFile(Intent intent){
		if(intent==null) return;
		Uri data=intent.getData();
		if(data!=null){
			try{
				currentPlay=-2;
				InputStream inp=getContentResolver().openInputStream(data);
				int type=-1;
				String f=data.getPath().toLowerCase();
				if(f.endsWith(".mid")) type=0;
				else if(f.endsWith(".xm")) type=1;
				NativePlayer.reset();
				byte[] b=Util.read(inp);
				NativePlayer.playBytes(b,type);
				setChannelArgs();
			}catch(FileNotFoundException e){
				Logger.getDef().e(e);
			}
		}
		setIntent(null);
	}
	// 打开已连接的设备
	private void openMidiDevice(MidiDeviceInfo deviceInfo){
		if(Build.VERSION.SDK_INT>=Build.VERSION_CODES.M){
			midiManager.openDevice(deviceInfo,new MidiManager.OnDeviceOpenedListener(){
				@Override
				public void onDeviceOpened(MidiDevice device){
					if(device!=null){
						MidiOutputPort inputPort=device.openOutputPort(0); // 打开第一个输入端口
						inputPort.connect(new MyMidiReceiver()); // 绑定自定义接收器
					}
				}
			},new Handler(Looper.getMainLooper()));
		}
	}
	public void setDetune(View v){
		LinearLayout ll=new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		final TextView tv=new TextView(this);
		final SeekBar seek=new SeekBar(this);
		ll.addView(tv);
		ll.addView(seek);
		seek.setMax(1000);
		seek.setProgress((int)(detune*1000));
		tv.setText(detune+"");
		seek.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
			@Override
			public void onProgressChanged(SeekBar p1,int p2,boolean p3){
				detune=p2/1000f;
				tv.setText(detune+"");
				setChannelArgs();
			}
			@Override
			public void onStartTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
			@Override
			public void onStopTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
		});
		new MyDialog.Builder(this).setTitle("设置Detune")
								  .setView(ll)
								  .setPositiveButton("确定",null)
								  .show();
	}
	public void expr(View v){
		LinearLayout ll=new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		final EditText tv=new EditText(this);
		tv.setText(sendTo);
		final EditText tv3=new EditText(this);
		tv3.setText(replaceInst);
		final EditText tv2=new EditText(this);
		tv2.setText(mainExpr);
		ll.addView(tv);
		ll.addView(tv3);
		ll.addView(tv2);
		final Button b=new Button(this);
		b.setText("发送至通道");
		ll.addView(b);
		final Button c=new Button(this);
		c.setText("替换乐器");
		ll.addView(c);
		final OnClickListener ocl;
		b.setOnClickListener(ocl=new OnClickListener(){
			@Override
			public void onClick(View p1){
				try{
					sendTo=tv.getText()+"";
					mainExpr=tv2.getText()+"";
					replaceInst=tv3.getText()+"";
					//					if(p1==b){
					//						Parser.parse(mainExpr,Parser.parseInts(sendTo));
					//					}
					//					else if(p1==c){
					//						Parser.replace(mainExpr,Parser.parseInts(replaceInst));
					//					}
				}catch(Exception e){
					e.printStackTrace();
					AndroidUtil.toast("输入有误");
				}
			}
		});
		c.setOnClickListener(ocl);
		new MyDialog.Builder(this).setTitle("表达式")
								  .setView(ll)
								  .setNegativeButton("返回",null)
								  .show();
	}
	public void centerChannel(View v){
		for(int i=0;i<16;i++){
			NativePlayer.postEvent(0xb0+i,MIDIFile.CC.PAN,64);
		}
	}
	public void setChorus(View v){
		LinearLayout ll=new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		final TextView tv1=new TextView(this);
		final SeekBar s1=new SeekBar(this);
		final TextView tv2=new TextView(this);
		final SeekBar s2=new SeekBar(this);
		final TextView tv22=new TextView(this);
		final SeekBar s22=new SeekBar(this);
		final TextView tv3=new TextView(this);
		final SeekBar s3=new SeekBar(this);
		final TextView tv4=new TextView(this);
		final SeekBar s4=new SeekBar(this);
		s1.setMax(1000);
		s2.setMax(1000);
		s22.setMax(1000);
		s3.setMax(2000);
		s4.setMax(1000);
		ll.addView(tv1);
		ll.addView(s1);
		ll.addView(tv2);
		ll.addView(s2);
		ll.addView(tv22);
		ll.addView(s22);
		ll.addView(tv3);
		ll.addView(s3);
		ll.addView(tv4);
		ll.addView(s4);
		OnSeekBarChangeListener socl=new OnSeekBarChangeListener(){
			@Override
			public void onProgressChanged(SeekBar p1,int p2,boolean p3){
				if(p1==s1){
					chorusDepth=p2;
					tv1.setText(String.format("深度(%.2fms)",chorusDepth));
				}
				else if(p1==s2){
					chorusRate1=p2/100f;
					tv2.setText(String.format("左频率(%.2fHz)",chorusRate1));
				}
				else if(p1==s22){
					chorusRate2=p2/100f;
					tv22.setText(String.format("右频率(%.2fHz)",chorusRate2));
				}
				else if(p1==s3){
					chorusFeedback=(p2-1000f)/1000f;
					tv3.setText(String.format("反馈(%.1f%%)",chorusFeedback*100));
				}
				else if(p1==s4){
					chorusRatio=p2/1000f;
					tv4.setText(String.format("干湿比(%.1f%%)",chorusRatio*100));
				}
				setChannelArgs();
			}
			@Override
			public void onStartTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
			@Override
			public void onStopTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
		};
		s1.setOnSeekBarChangeListener(socl);
		s2.setOnSeekBarChangeListener(socl);
		s22.setOnSeekBarChangeListener(socl);
		s3.setOnSeekBarChangeListener(socl);
		s4.setOnSeekBarChangeListener(socl);
		s1.setProgress((int)(chorusDepth));
		s2.setProgress((int)(chorusRate1*100));
		s22.setProgress((int)(chorusRate2*100));
		s3.setProgress((int)(chorusFeedback*1000+1000));
		s4.setProgress((int)(chorusRatio*1000));
		new MyDialog.Builder(this).setTitle("设置Chorus")
								  .setView(ll)
								  .setPositiveButton("确定",null)
								  .show();
	}
	public void setReverb(View v){
		LinearLayout ll=new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		final TextView tv1=new TextView(this);
		final SeekBar sRoomSize=new SeekBar(this);
		final TextView tv2=new TextView(this);
		final SeekBar sDamper=new SeekBar(this);
		final TextView tv3=new TextView(this);
		final SeekBar sdry=new SeekBar(this);
		final TextView tv4=new TextView(this);
		sRoomSize.setMax(1000);
		sDamper.setMax(2000);
		sdry.setMax(1000);
		sRoomSize.setProgress((int)(reverbRoomSize*1000));
		sDamper.setProgress((int)(reverbDamper*1000));
		sdry.setProgress((int)(reverbWetRatio*1000));
		tv1.setText("房间大小(%)");
		tv2.setText("高频衰减(%)");
		tv3.setText("干湿比");
		ll.addView(tv1);
		ll.addView(sRoomSize);
		ll.addView(tv2);
		ll.addView(sDamper);
		ll.addView(tv3);
		ll.addView(sdry);
		ll.addView(tv4);
		OnSeekBarChangeListener socl=new OnSeekBarChangeListener(){
			@Override
			public void onProgressChanged(SeekBar p1,int p2,boolean p3){
				if(p1==sRoomSize){
					reverbRoomSize=p2/1000f;
				}
				else if(p1==sDamper){
					reverbDamper=p2/1000f;
				}
				else if(p1==sdry){
					reverbWetRatio=p2/1000f;
				}
				setChannelArgs();
			}
			@Override
			public void onStartTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
			@Override
			public void onStopTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
		};
		sRoomSize.setOnSeekBarChangeListener(socl);
		sDamper.setOnSeekBarChangeListener(socl);
		sdry.setOnSeekBarChangeListener(socl);
		new MyDialog.Builder(this).setTitle("设置Reverb")
								  .setView(ll)
								  .setPositiveButton("确定",null)
								  .show();
	}
	public void setAPitch(View v){
		MyDialog.Prompt prompt=new MyDialog.Prompt(ctx,"A音高",""+AFreq);
		final EditText ed=prompt.getEditText();
		DialogInterface.OnClickListener dl=new DialogInterface.OnClickListener(){
			@Override
			public void onClick(DialogInterface dialog,int which){
				if(which==DialogInterface.BUTTON_POSITIVE){
					try{
						AFreq=Float.parseFloat(ed.getText()+"");
						setChannelArgs();
					}catch(Exception e){}
				}
			}
		};
		new MyDialog.Builder(this).setTitle("设置A音高")
								  .setView(prompt.get())
								  .setPositiveButton("确定",dl)
								  .setNegativeButton("取消",null)
								  .show();
	}
	public void keyboard(View v){
		startActivity(new Intent(this,KeyBoardActivity.class));
	}
	public void reset(View v){
		currentPlay=-2;
		NativePlayer.reset();
	}
	public void setSR(View v){
		LinearLayout ll=new LinearLayout(this);
		ll.setOrientation(LinearLayout.VERTICAL);
		final TextView tv=new TextView(this);
		final SeekBar seek=new SeekBar(this);
		ll.addView(tv);
		ll.addView(seek);
		seek.setMax(192000-4000);
		seek.setProgress(sampleRate-4000);
		tv.setText(sampleRate+"Hz");
		seek.setOnSeekBarChangeListener(new OnSeekBarChangeListener(){
			@Override
			public void onProgressChanged(SeekBar p1,int p2,boolean p3){
				tv.setText((p2+4000)+"Hz");
			}
			@Override
			public void onStartTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
			@Override
			public void onStopTrackingTouch(SeekBar p1){
				// TODO: Implement this method
			}
		});
		new MyDialog.Builder(this).setTitle("设置采样率")
								  .setView(ll)
								  .setNegativeButton("返回",new DialogInterface.OnClickListener(){
									  @Override
									  public void onClick(DialogInterface p1,int p2){
									  }
								  })
								  .setPositiveButton("确定",new DialogInterface.OnClickListener(){
									  @Override
									  public void onClick(DialogInterface p1,int p2){
										  int p2p=seek.getProgress();
										  sampleRate=p2p+4000;
										  NativePlayer.setSampleRate(sampleRate);
									  }
								  })
								  .show();
	}
}
